print non-fatal errors to stdout instead of stderr
authorLiigo Zhuang <com.liigo@gmail.com>
Sun, 14 Dec 2014 13:34:33 +0000 (21:34 +0800)
committerLiigo Zhuang <com.liigo@gmail.com>
Sun, 14 Dec 2014 13:34:33 +0000 (21:34 +0800)
e.g. docopt treat version as non-fatal error

Fixes #1033

src/cargo/core/shell.rs
src/cargo/lib.rs

index 7a83ac4914fee89615b41d316b7d311964d84ab4..10965255519996bd728e358dc39dc485f220412b 100644 (file)
@@ -77,6 +77,10 @@ impl MultiShell {
     pub fn set_verbose(&mut self, verbose: bool) {
         self.verbose = verbose;
     }
+
+    pub fn get_verbose(&self) -> bool {
+        self.verbose
+    }
 }
 
 pub type ShellCallback<'a> = |&mut Shell|:'a -> IoResult<()>;
index 2dd20824f90d279485deff16d65ced0953c942a4..8943c3e5d0a7199bfcf8bba1984aafdd5e1952e3 100644 (file)
@@ -32,7 +32,7 @@ use serialize::{Decoder, Encoder, Decodable, Encodable, json};
 use docopt::Docopt;
 
 use core::{Shell, MultiShell, ShellConfig};
-use term::color::{BLACK};
+use term::color::{BLACK, RED};
 
 pub use util::{CargoError, CliError, CliResult, human};
 
@@ -178,35 +178,54 @@ pub fn shell(verbose: bool) -> MultiShell {
     MultiShell::new(out, err, verbose)
 }
 
+
+// `output` print variant error strings to either stderr or stdout.
+// For fatal errors, print to stderr;
+// and for others, e.g. docopt version info, print to stdout.
+fn output(caption: Option<String>, detail: Option<String>,
+          shell: &mut MultiShell, fatal: bool) {
+    let std_shell = if fatal {shell.err()} else {shell.out()};
+    if let Some(caption) = caption {
+        let color = if fatal {RED} else {BLACK};
+        let _ = std_shell.say(caption, color);
+    }
+    if let Some(detail) = detail {
+        let _ = std_shell.say(detail, BLACK); // always black
+    }
+}
+
 pub fn handle_error(err: CliError, shell: &mut MultiShell) {
     log!(4, "handle_error; err={}", err);
 
     let CliError { error, exit_code, unknown } = err;
+    let verbose = shell.get_verbose();
+    let fatal = exit_code == 1; // exit_code == 0 is non-fatal error
 
     if unknown {
-        let _ = shell.error("An unknown error occurred");
+        output(Some("An unknown error occurred".to_string()), None, shell, fatal);
     } else if error.to_string().len() > 0 {
-        let _ = shell.error(error.to_string());
+        output(Some(error.to_string()), None, shell, fatal);
     }
 
     if error.cause().is_some() || unknown {
-        let _ = shell.concise(|shell| {
-            shell.err().say("\nTo learn more, run the command again with --verbose.", BLACK)
-        });
+        if !verbose {
+            output(None,
+                   Some("\nTo learn more, run the command again with --verbose.".to_string()),
+                   shell, fatal);
+        }
     }
 
-    let _ = shell.verbose(|shell| {
+    if verbose {
         if unknown {
-            let _ = shell.error(error.to_string());
+            output(Some(error.to_string()), None, shell, fatal);
         }
         if let Some(detail) = error.detail() {
-            let _ = shell.err().say(format!("{}", detail), BLACK);
+            output(None, Some(detail), shell, fatal);
         }
         if let Some(err) = error.cause() {
             let _ = handle_cause(err, shell);
         }
-        Ok(())
-      });
+    }
 
     std::os::set_exit_status(exit_code as int);
 }